package info.magnolia.blossom.sample.cv;

import info.magnolia.blossom.sample.cv.model.CurriculumVitae;
import info.magnolia.blossom.sample.cv.model.SearchResult;
import info.magnolia.blossom.sample.cv.service.CVService;
import info.magnolia.jcr.util.PropertyUtil;
import info.magnolia.module.blossom.annotation.TabFactory;
import info.magnolia.module.blossom.annotation.Template;
import info.magnolia.module.blossom.annotation.TemplateDescription;
import info.magnolia.module.blossom.dialog.TabBuilder;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.jcr.Node;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: peterbalazs
 * Date: 2/20/13
 * Time: 5:06 PM
 * To change this template use File | Settings | File Templates.
 */
@Template(title = "List of CVs", id = "blossomSample:components/listofcvs")
@TemplateDescription("List of available CVs")
@Controller
public class ListOfCVs {

    public static final String PARAM_CV_ID = "cvid";
    public static final String PARAM_CV_LIST_SEARCH_CRITERIA = "searchFor";

    private static final String PARAM_PAGE_NUMBER = "page";
    private static final String PARAM_ITEMS_PER_PAGE = "ipp";

    private static final String VAR_ITEMS_PER_PAGE = "itemsPerPage";
    private static final String VAR_SHOW_TOP_PAGINATION = "topPagination";
    private static final String VAR_SHOW_BOTTOM_PAGINATION = "showBottomPagination";

    private static final int DEFAULT_ITEMS_PER_PAGE = 3;

    private static final Logger logger = Logger.getLogger(ListOfCVs.class);

    @Autowired
    private CVService cvService;

    @RequestMapping("/cvtemplate/listofcvs")
    public String render(final Node node, final ModelMap model, final HttpServletRequest request) {
        final String searchCriteria = request.getParameter(PARAM_CV_LIST_SEARCH_CRITERIA);
        final String strPageNumber = request.getParameter(PARAM_PAGE_NUMBER);
        int pageNumber = 1;
        if (StringUtils.isNotBlank(strPageNumber)) {
            try {
                pageNumber = Integer.parseInt(strPageNumber.trim());
            } catch (NumberFormatException nfe) {
                logger.warn("Invalid page number: " + strPageNumber);
            }
        }
        final String strItemsPerPage = PropertyUtil.getString(node, VAR_ITEMS_PER_PAGE, DEFAULT_ITEMS_PER_PAGE + "");
        int ipp = DEFAULT_ITEMS_PER_PAGE;
        if (StringUtils.isNotBlank(strItemsPerPage)) {
            try {
                ipp = Integer.parseInt(strItemsPerPage);
                if (ipp <= 0) {
                    logger.warn("Invalid items per page setting: " + strItemsPerPage);
                    ipp = DEFAULT_ITEMS_PER_PAGE;
                }
            } catch (NumberFormatException nfe) {
                logger.warn("Invalid items per page setting: " + strItemsPerPage);
            }
        }
        final boolean showTopPagination = PropertyUtil.getBoolean(node, VAR_SHOW_TOP_PAGINATION, true);
        final boolean showBottomPagination = PropertyUtil.getBoolean(node, VAR_SHOW_BOTTOM_PAGINATION, true);
        final SearchResult sr = getSearchResults(searchCriteria, pageNumber, ipp);  // TODO get items per page from settings
        model.put("sr", sr);
        model.put("criteria", searchCriteria);
        model.put("showTopPagination", showTopPagination);
        model.put("showBottomPagination", showBottomPagination);
        return "components/listOfCVs.jsp";
    }

    @TabFactory("Settings")
    public void settingsTab(final TabBuilder tab) {
        tab.addUuidLink("viewLink", "View Page Link", "Browse internal links and select the correct one for the CV view page");
        tab.addUuidLink("deleteConfirmationLink", "Delete Confirmation Link", "Confirmation page for deleting the selected CV");
        tab.addUuidLink("editLink", "Edit Page Link", "Browse internal links and select the correct one for the edit CV page");
        tab.addEdit(VAR_ITEMS_PER_PAGE, "Items per Page", "The maximum number of CVs shown on one page");
        tab.addCheckbox(VAR_SHOW_TOP_PAGINATION, "Top Pagination", "Show pagination above the results");
        tab.addCheckbox(VAR_SHOW_BOTTOM_PAGINATION, "Bottom Pagination", "Show pagination below the results");
    }

    @TabFactory("Styling")
    public void stylingTab(final TabBuilder tab) {
        tab.addEdit("componentClass", "Component Class", "CSS class(es) to be added to the component-surrounding DIV");
    }

    private SearchResult getSearchResults(final String searchCriteria, final int pageNumber, final int itemsPerPage)
    {
        final SearchResult sr = new SearchResult();
        final List<CurriculumVitae> fullList = cvService.getAllCVs(searchCriteria);
        sr.setItemsPerPage(itemsPerPage > 0 ? itemsPerPage : DEFAULT_ITEMS_PER_PAGE);
        sr.setTotalResults(fullList.size());
        int totalPages = (sr.getTotalResults() / sr.getItemsPerPage());
        if (sr.getTotalResults() % sr.getItemsPerPage() > 0) {
            totalPages++;
        }
        sr.setTotalPages(totalPages);
        if (pageNumber > totalPages) {
            sr.setCurrentPage(1);
        } else {
            sr.setCurrentPage(pageNumber);
        }
        sr.setShowPrevButton(sr.getCurrentPage() > 1);
        sr.setShowNextButton(sr.getCurrentPage() < totalPages);
        sr.setShowPagination(totalPages > 1);
        if (totalPages > 1) {
            final int startPos = (sr.getCurrentPage() - 1) * sr.getItemsPerPage();
            int endPos = startPos + sr.getItemsPerPage();
            if (endPos > fullList.size()) {
                endPos = fullList.size();
            }
            sr.setList(new ArrayList<CurriculumVitae>(fullList.subList(startPos, endPos)));
        } else {
            sr.setList(fullList);
        }
        return sr;
    }

}
